package com.zlyx.easy.core.utils;

import java.text.SimpleDateFormat;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.zlyx.easy.core.collections.EasyList;
import com.zlyx.easy.core.map.EasyMap;

/**
 * <p>
 * JSON操作工具
 * </p>
 *
 * @author 赵光
 * @since 2019年4月8日
 */
public class JsonUtils {

	private static Logger logger = LoggerFactory.getLogger(JsonUtils.class);

	private static ObjectMapper objectMapper;

	public static ObjectMapper mapper() {
		if (objectMapper == null) {
			objectMapper = new ObjectMapper();
			objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
			objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
			objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 反序列化时忽略不存在的属性
			objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // 序列化时将LocalDateTime转换为时间戳格式
			objectMapper.registerModule(new JavaTimeModule());
		}
		return objectMapper;
	}

	/**
	 * 实例化pretty对象
	 * 
	 * @return
	 */
	public static ObjectWriter pretty() {
		return mapper().writer(new DefaultPrettyPrinter());
	}

	/**
	 * 格式化输出
	 * 
	 * @param o
	 * @param class1
	 * @return
	 */
	public static <T> void print(Object o) {
		try {
			System.out.println(pretty(o));
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
		}
	}

	/**
	 * 格式化输出
	 * 
	 * @param o
	 * @return
	 * @throws JsonProcessingException
	 */
	public static String pretty(Object o) throws JsonProcessingException {
		return pretty().writeValueAsString(o);
	}

	/**
	 * 转换为json
	 * 
	 * @param o
	 * @return
	 * @throws Exception
	 */
	public static String toJson(Object o) {
		try {
			if (ObjectUtils.isEmpty(o)) {
				return null;
			}
			if (String.class != o.getClass() && o.getClass().getName().contains("java.lang")) {
				o = String.valueOf(o);
			}
			if (String.class != o.getClass()) {
				o = mapper().writeValueAsString(o);
			}
			return (String) o;
		} catch (JsonProcessingException e) {
			logger.error(e.getMessage(), e);
		}
		return null;
	}

	/**
	 * 解析json
	 * 
	 * @param text
	 * @param cls
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings("unchecked")
	public static <T> T fromJson(Object o, Class<T> cls) throws Exception {
		if (o == null) {
			return null;
		}
		if (o.getClass() == cls) {
			return (T) o;
		}
		return ObjectUtils.isEmpty(o) ? null : mapper().readValue(toJson(o), cls);
	}

	/**
	 * 解析json
	 * 
	 * @param o
	 * @param typeReference
	 * @return
	 * @throws Exception
	 */
	public static <T> T fromJson(Object o, TypeReference<T> typeReference) throws Exception {
		return ObjectUtils.isEmpty(o) ? null : mapper().readValue(toJson(o), typeReference);
	}

	/**
	 * 转List
	 * 
	 * @param <T>
	 * @param o
	 * @return
	 * @throws Exception
	 */
	public static <T> EasyList<T> toList(Object o) throws Exception {
		return fromJson(o, new TypeReference<EasyList<T>>() {
		});
	}

	/**
	 * 转Map
	 * 
	 * @param <K>
	 * @param <V>
	 * @param text
	 * @return
	 * @throws Exception
	 */
	public static <K, V> EasyMap<K, V> toMap(Object o) throws Exception {
		return fromJson(o, new TypeReference<EasyMap<K, V>>() {
		});
	}

}
